﻿// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#if !NET40
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using CuteAnt.AsyncEx;
using CuteAnt.Runtime;

namespace CuteAnt.IO.Pipelines
{
  internal sealed class PipelineWriterStream : Stream
  {
    private readonly IPipeWriter _writer;
    private readonly bool _automaticFlushing;

    public PipelineWriterStream(IPipeWriter writer, bool automaticFlushing)
    {
      _writer = writer;
      _automaticFlushing = automaticFlushing;
    }

    public override bool CanRead => false;

    public override bool CanSeek => false;

    public override bool CanWrite => true;

    public override long Length => throw new NotSupportedException();

    public override long Position
    {
      get => throw new NotSupportedException();
      set => throw new NotSupportedException();
    }

    public override void Flush()
    {
      throw new NotSupportedException();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
      throw new NotSupportedException();
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
      throw new NotSupportedException();
    }

    public override void SetLength(long value)
    {
      throw new NotSupportedException();
    }

    public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
    {
      Write(buffer, offset, size);
      return new CompletedAsyncResult(callback, state);
    }

    public override void EndWrite(IAsyncResult result)
    {
      CompletedAsyncResult.End(result);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
      var output = _writer.Alloc();
      output.Write(new ReadOnlySpan<byte>(buffer, offset, count));
      //InternalWrite(output, buffer, offset, count);
      if (_automaticFlushing) { output.FlushAsync().GetResult(); }
    }

    public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
    {
      if (cancellationToken.IsCancellationRequested)
      {
        return AsyncUtils.FromCanceled(cancellationToken);
      }

      var output = _writer.Alloc();
      output.Write(new ReadOnlySpan<byte>(buffer, offset, count));
      //InternalWrite(output, buffer, offset, count);
      if (_automaticFlushing) { return output.FlushAsyncAwaited(cancellationToken); }
      return TaskConstants.Completed;
    }

    //private static void InternalWrite(in WritableBuffer output, byte[] buffer, int offset, int count)
    //{
    //  var writer = new WritableBufferWriter(output);
    //  writer.Write(buffer, offset, count);
    //}
  }
}
#endif
